home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Panorama / Panorama - Disk 19D (1987-07-22)(Pacific North-West Amigas Club)[WB].zip / Panorama - Disk 19D (1987-07-22)(Pacific North-West Amigas Club)[WB].adf / HackBench / hbicon.c < prev    next >
C/C++ Source or Header  |  1987-07-14  |  21KB  |  683 lines

  1. /****************************************************************
  2. /*                                *
  3. /*    HackBench - Part 2 of 4 - hbicon.c - Icon Routines    *
  4. /*                                *
  5. /*    Copyright (C) 1987 by Bill Kinnersley            *
  6. /*    CS Dept, Washington State Univ, Pullman, WA 99164    *
  7. /*                                *
  8. /*    Permission granted to redistribute this program        *
  9. /*    provided the copyright notice remains intact.        *
  10. /*    May not be used as part of any commercial product.    *
  11. /*                                *
  12. /****************************************************************/
  13.  
  14. #include "hb.h"
  15.  
  16. extern struct DosInfo *rnInfo;
  17. extern struct MsgPort *IDCMPPort, WBPort;
  18. extern long IDCMPBit, WBBit;
  19.  
  20. extern USHORT x_ptr[];
  21. extern struct Gadget
  22.     vs_gad, hs_gad, ren_gad, up_gad, dm_gad, lm_gad, rm_gad;
  23. extern struct PropInfo hs_knob, vs_knob;
  24.  
  25. extern struct Rectangle rect;
  26. extern char *type[], *title;
  27. extern short wbFlags, toolsRunning;
  28. extern struct List selObjs, wbObjs, utilObjs;
  29. extern int drawobj(), clearobj(), compobj(), openobj(), closeobj();
  30. extern char *rindex();
  31.  
  32. struct MyWBObject *lastObj, *hitObj, *hitWinObj, *findObj(), *makeWbObj();
  33. struct Window *wbWin, *oldWin, *curWin, *hitWin, *errWin;
  34. struct IntuiMessage saveMsg;
  35. struct Layer_Info *li;
  36.  
  37. ULONG downSecs, downMicros, upSecs, upMicros;
  38. short oldX, oldY, dblclik, debug=FALSE;
  39. char buf1[61], buf2[61];
  40.  
  41. struct DeviceList *vol();
  42. BPTR getlock();
  43. long tooSoon();
  44.  
  45. main() {
  46.     struct Message *msg;
  47.     struct WBStartup *wbmsg;
  48.     long mask;
  49.     BPTR seg;
  50.  
  51.     openAll();
  52.     curWin = wbWin; /* Current window is the backdrop */
  53.     li = &wbWin->WScreen->LayerInfo;
  54.  
  55.     findDisks();
  56.     makeMenu();
  57.     OnMenu(wbWin, REDRAW); OnMenu(wbWin, VERS);
  58.  
  59.     avail();
  60.  
  61.     while (1) { /* We have two ports to monitor at once */
  62.         mask = Wait(IDCMPBit | WBBit);
  63.         if (mask & WBBit) while (msg = GetMsg(WBPort)) {
  64.             /* Unload the tool that just exited */
  65.             wbmsg = (struct WBStartup *)msg;
  66.             if (debug) printf("Unloading\n");
  67.             if (seg = wbmsg->sm_Segment) UnLoadSeg(seg);
  68.             FreeMem(wbmsg->sm_ArgList,
  69.             wbmsg->sm_NumArgs*(long)sizeof(struct WBArg));
  70.             FreeMem(msg, (long)sizeof(struct WBStartup));
  71.             toolsRunning--;
  72.         }
  73.         if (mask & IDCMPBit) while (msg = GetMsg(IDCMPPort))
  74.             doIDCMP(msg);
  75.     }
  76. }
  77.  
  78. doIDCMP(msg) struct IntuiMessage *msg; {
  79.     struct MyWBObject *obj;
  80.     struct DeviceList *diDev, *ptr;
  81.     char diskName[31];
  82.     struct Node *node;
  83.  
  84. /*stc*/    saveMsg = *msg;
  85.     ReplyMsg(msg);
  86.     curWin = oldWin = saveMsg.IDCMPWindow;
  87.     switch (saveMsg.Class) {
  88.     case CLOSEWINDOW :
  89.         obj = (struct MyWBObject *)oldWin->UserData;
  90.         closeobj(obj);
  91.         clearSel();
  92.         avail();
  93.         break;
  94.     case MENUPICK: doMenu(saveMsg.Code); break;
  95.     case MOUSEBUTTONS:
  96.         switch(saveMsg.Code) {
  97.         case SELECTDOWN: doSelDown(); break;
  98.         case SELECTUP: doSelUp(); break;
  99.         }
  100.         break;
  101.     case GADGETUP: doGadUp(); break;
  102.     case GADGETDOWN: doGadDown(); break;
  103.     case DISKINSERTED:
  104.     /*Delay(10L);*/ /* May be necessary */
  105.         /* Scan the Device List for a Volume that does not
  106.         appear on the Master List of WBObjects */
  107.         diDev = (struct DeviceList *) BADDR(rnInfo->di_DevInfo);
  108.         for (ptr=diDev; ptr; ptr=(struct DeviceList *)
  109.         BADDR(ptr->dl_Next)) if (ptr->dl_Type==DLT_VOLUME) {
  110.         bs2cs(diskName, ptr->dl_Name);
  111.         if (!FindName(&wbObjs, diskName)) break;
  112.         }
  113.         if (!ptr) break;
  114.         instDisk(diskName); /* Make a new disk object */
  115.         refresh(wbWin);
  116.         break;
  117.     case DISKREMOVED:
  118.     Delay(10L); /* This does seem to be necessary */
  119.         /* For each disk object, check to see if it's still
  120.         on the Device List */
  121.         diDev = (struct DeviceList *) BADDR(rnInfo->di_DevInfo);
  122.         for (node=wbObjs.lh_Head; node->ln_Succ; node=node->ln_Succ) {
  123.         obj = (struct MyWBObject *)node;
  124.         if (obj->wo_Type!=WBDISK) continue;
  125.         for (ptr=diDev; ptr; ptr=(struct DeviceList *)
  126.             BADDR(ptr->dl_Next)) if (ptr->dl_Type==DLT_VOLUME) {
  127.             bs2cs(diskName, ptr->dl_Name);
  128.             if (strcmp(diskName, obj->wo_Name)==0) break;
  129.         }
  130.         if (ptr) continue;
  131.         clearobj(obj); /* Not found--get rid of it */
  132.         deleteobj(obj);
  133.         break;
  134.         }
  135.         refresh(wbWin);
  136.         break;
  137.     case REFRESHWINDOW:
  138.         if (debug)
  139.         printf("Window %lx is SIMPLY REFRESHING!\n", curWin);
  140.         BeginRefresh(curWin);
  141.         refresh(curWin);
  142.         EndRefresh(curWin, TRUE);
  143.         break;
  144.     case NEWSIZE:
  145.         reclip(curWin);
  146.         resize(curWin);
  147.         break;
  148.     }
  149. }
  150.  
  151. clearSel() { /* Purge the Select List */
  152.     struct Node *node;
  153.  
  154.     doList(&selObjs, SEL, drawobj, NORM);
  155.     while (node = RemHead(&selObjs)) node->ln_Succ = NULL;
  156.     /* So we can tell later whether a given object
  157.         is still on the List */
  158.     lastObj = NULL;
  159.     OffMenu(wbWin, OPEN); OffMenu(wbWin, CLOZE);
  160.     OffMenu(wbWin, DUP); OffMenu(wbWin, RENAME);
  161.     OffMenu(wbWin, INFO); OffMenu(wbWin, INIT);
  162.     OffMenu(wbWin, SNAP); OffMenu(wbWin, DISCARD);
  163. }
  164.  
  165. doOpen() {
  166.     struct Node *node;
  167.     struct MyWBObject *obj;
  168.  
  169.     /* If there's a tool or project on the Select List, run it.
  170.         Otherwise, just open everybody on the List */
  171.     for (node=selObjs.lh_Head; node->ln_Succ; node=node->ln_Succ) {
  172.         obj = OBJ(node,SEL);
  173.         if (obj->wo_Type==WBTOOL || obj->wo_Type==WBPROJECT)
  174.             {run(obj); return;}
  175.     }
  176.     doList(&selObjs, SEL, openobj);
  177. }
  178.  
  179. /* doSelDown does three things:
  180.     Detects and handles double clicks
  181.     Accumulates the extended selection list
  182.     Toggles menu items
  183. */
  184. doSelDown() {
  185.     struct MyWBObject *obj;
  186.     struct Node *node;
  187.  
  188.     if (errWin) {SetWindowTitles(errWin,-1L,title); errWin=NULL;}
  189.     if (obj = findObj(saveMsg.MouseX, saveMsg.MouseY, curWin)) {
  190.         /* Hit an icon */
  191.         if (dblclik = ((obj==lastObj) && DoubleClick(downSecs,
  192.         downMicros, saveMsg.Seconds, saveMsg.Micros))) {
  193.         /* Double click */
  194.             if (debug) printf("Double click\n");
  195.             saveMsg.Seconds -= 20L; /* To prevent triple clicks */
  196.             doOpen();
  197.             OffMenu(wbWin, OPEN); OnMenu(wbWin, CLOZE);
  198.             avail();
  199.         }
  200.  
  201.         else { /* Single click so far */
  202.         if (debug) printf("Single click\n");
  203.         SetPointer(oldWin, x_ptr, 12L, 12L, -6L, -6L);
  204.         if (saveMsg.Qualifier & SHIFT) {
  205.         /* Extended selection rules out some operations */    
  206.             OffMenu(wbWin, DUP); OffMenu(wbWin, RENAME);
  207.             OffMenu(wbWin, INFO);
  208.         }
  209.         else {
  210.             doList(&selObjs, SEL, drawobj, NORM);
  211.             while (node = RemHead(&selObjs))
  212.             node->ln_Succ = node->ln_Pred = NULL;
  213.             OnMenu(wbWin, DUP); OnMenu(wbWin, RENAME);
  214.             OnMenu(wbWin, INFO);
  215.         }
  216.         OnMenu(wbWin, SNAP);
  217.         if (!obj->wo_SelectNode.ln_Succ) /* Not yet selected */
  218.             AddHead(&selObjs, &obj->wo_SelectNode);
  219.         /* Exec gets confused if a node is in the same list twice */
  220.         drawobj(obj, HIGH); /* Highlight it */
  221.         /* Did I hit an open drawer? */
  222.         if (obj->wo_DrawerData
  223.             && obj->wo_DrawerData->dd_DrawerWin)
  224.             {OnMenu(wbWin, CLOZE); OffMenu(wbWin, OPEN);}
  225.         /* Either a closed drawer or a tool */
  226.         /* Tools can always be opened */
  227.         else {OnMenu(wbWin, OPEN); OffMenu(wbWin, CLOZE);}
  228.  
  229.         lastObj = obj; oldX = saveMsg.MouseX; oldY = saveMsg.MouseY;
  230.         downSecs = saveMsg.Seconds; downMicros = saveMsg.Micros;
  231.         }
  232.     }
  233.     else clearSel();        /* Didn't hit an icon */
  234. }
  235.  
  236. doSelUp() {
  237.     struct Layer *layer;
  238.     struct Window *w;
  239.     short dx, dy;
  240.     BPTR lock, lock2;
  241.     struct MyDrawerData *dd;
  242.  
  243.     if (dblclik) {dblclik = FALSE; return;}
  244.     ClearPointer(oldWin);
  245.     if (!lastObj) return;
  246.     curWin = oldWin;
  247.     upSecs = saveMsg.Seconds; upMicros = saveMsg.Micros;
  248.  
  249. /* Selectup msg is sent back to the window where selectdown occurred,
  250. (oldWin), so we have to search the layers for the real window */
  251.  
  252.     layer = WhichLayer(li, (long)(saveMsg.MouseX + oldWin->LeftEdge),
  253.         (long)(saveMsg.MouseY + oldWin->TopEdge));
  254.     for (hitWin=wbWin->WScreen->FirstWindow; hitWin;
  255.     hitWin=hitWin->NextWindow)
  256.         if (hitWin->WLayer==layer) break;
  257.     if (!hitWin) return; /* Shouldn't happen */
  258.  
  259.     if (!(hitWin->Flags & WBENCHWINDOW))
  260.     {error("That's somebody else's window"); return;}
  261.     if (hitWin!=wbWin) if (lastObj->wo_Type==WBDISK) 
  262.     {error("Disks can't be moved into windows"); return;}
  263.     if (lastObj->wo_Type==WBGARBAGE)
  264.     if (hitWin!=lastObj->wo_IconWin)
  265.     {error("A trashcan must stay in its own window"); return;}
  266.     if (lastObj->wo_Type==WBDRAWER)
  267.     if (hitWin==lastObj->wo_DrawerData->dd_DrawerWin)
  268.     /* You tried to move an icon into its own open window, dodo */
  269.     {error("Hey, that's me!"); return;}
  270.  
  271.     hitWinObj = (struct MyWBObject *)hitWin->UserData;
  272.     /* hitWinObj may be NULL if hitWin is the backdrop */
  273.     dx = saveMsg.MouseX + oldWin->LeftEdge - hitWin->LeftEdge;
  274.     dy = saveMsg.MouseY + oldWin->TopEdge - hitWin->TopEdge;
  275.     hitObj = findObj(dx, dy, hitWin);
  276.     if (debug) printf("SelUp hitObj=%lx hitWin=%lx\n", hitObj, hitWin);
  277.  
  278.     if ((!hitObj) || (hitObj==lastObj))
  279.     {moveObj(&selObjs, SEL, dx - oldX, dy - oldY); return;}
  280.  
  281.     /* So from here on we must have hit a new icon */
  282.     if (debug) printf("Hit <%s>, a %s\n",
  283.     hitObj->wo_Name, type[hitObj->wo_Type]);
  284.  
  285.     switch (hitObj->wo_Type) {
  286.     case WBDISK: if (lastObj->wo_Type==WBDISK)
  287.         {error("DiskCopy not implemented"); return;}
  288.     if (lastObj->wo_Type==WBGARBAGE)
  289.         {error("A trashcan must stay in its own window"); return;}
  290.     if (hitObj==lastObj->wo_Parent) break;
  291.     lock = getlock(lastObj);
  292.     if (vol(lock)==vol(hitObj->wo_Lock)) {
  293.         /* On same disk--just rename */
  294.         strcpy(buf1, lastObj->wo_Name); strcpy(buf2, lastObj->wo_Name);
  295.         if (debug) printf("Renaming %lx <%s> to %lx <:%s>\n",
  296.         lock, lastObj->wo_Name, hitObj->wo_Lock, lastObj->wo_Name);
  297.         strcat(buf1, ".info"); strcat(buf2, ".info");
  298.         renBoth(lock, buf1, hitObj->wo_Lock, buf2);
  299.         break;
  300.     }
  301.     /* Otherwise copy to another disk--not implemented */
  302.     if (debug) printf("I should copy %lx <%s> to %lx <%s:>\n",
  303.         lock, lastObj->wo_Name, hitObj->wo_Lock, hitObj->wo_Name);
  304.     return;
  305.  
  306.     case WBDRAWER:
  307.     case WBGARBAGE: /* Hit a drawer icon */
  308.     if (hitObj==lastObj->wo_Parent) break;
  309.     if (lastObj->wo_Type==WBDISK) if (hitWin!=wbWin)
  310.         {error("Can't move a disk into a drawer"); return;}
  311.     if (lastObj->wo_Type==WBGARBAGE)
  312.         {error("A trashcan must stay in its own window"); return;}
  313.  
  314.     strcpy(buf1, lastObj->wo_Name); strcpy(buf2, hitObj->wo_Name);
  315.     strcat(buf2, "/"); strcat(buf2, lastObj->wo_Name);
  316.     lock = getlock(lastObj); lock2 = getlock(hitObj);
  317.     if (debug) printf("Renaming %lx <%s> to %lx <%s>\n",
  318.         lock, buf1, lock2, buf2);
  319.     strcat(buf1, ".info"); strcat(buf2, ".info");
  320.     renBoth(lock, buf1, lock2, buf2);
  321.     break;
  322.     default:  /* Just let the icons overlap */
  323.     moveObj(&selObjs, SEL, dx-oldX, dy-oldY);
  324.     return;
  325.     }
  326.     goAway();
  327.     doResize();
  328. }
  329.  
  330. goAway() { /* Do move from one window to another */
  331.     struct MyDrawerData *dd;
  332.     struct Window *w;
  333.  
  334.     mark(lastObj->wo_IconWin);
  335.     clearobj(lastObj);
  336.     Remove(&lastObj->wo_Siblings);
  337.     lastObj->wo_Siblings.ln_Succ = NULL;
  338.     dd = hitObj->wo_DrawerData;
  339.     if (w=dd->dd_DrawerWin) { /* Destination window open */
  340.         AddHead(&dd->dd_Children, &lastObj->wo_Siblings);
  341.         lastObj->wo_Parent = hitObj;
  342.         lastObj->wo_IconWin = w;
  343.         mark(w);
  344.         Remove(lastObj); AddTail(&wbObjs, lastObj);
  345.         /* Rearrange, so that refresh() draws it last (on top) */
  346.     }
  347.     else deleteobj(lastObj);
  348. }
  349.  
  350. moveObj(list, off, x, y)
  351. struct List *list; long off; short x, y; {
  352.     struct Node *node;
  353.     struct MyWBObject *obj, *iconWinObj;
  354.     struct Window *w;
  355.     struct MyDrawerData *dd;
  356.     char *p;
  357.     BPTR lock, lock2;
  358.  
  359.     mark(hitWin);
  360.     hitWinObj = (struct MyWBObject *)hitWin->UserData;
  361.  
  362.     if (tooSoon()) return; /* If selup too soon, ignore */
  363.     doList(list, off, clearobj);
  364.     for (node=list->lh_Head; node->ln_Succ; node=node->ln_Succ) {
  365.     obj = OBJ(node,off);
  366.     if (debug)
  367.         printf("moveObj: %lx (%d %d) by (%d %d) from %lx to %lx\n",
  368.         obj, obj->wo_Gadget.LeftEdge, obj->wo_Gadget.TopEdge,
  369.         x, y, obj->wo_IconWin, hitWin);
  370.     iconWinObj = (struct MyWBObject *)obj->wo_IconWin->UserData;
  371.     mark(obj->wo_IconWin);
  372.     if (obj->wo_IconWin!=hitWin) { /* Changing windows */
  373.         /* Adjust the virtual coordinates */
  374.         if (obj->wo_IconWin!=wbWin) {
  375.         dd = iconWinObj->wo_DrawerData;
  376.         obj->wo_CurrentX -= dd->dd_CurrentX;
  377.         obj->wo_CurrentY -= dd->dd_CurrentY;
  378.         }
  379.         if (hitWin!=wbWin) {
  380.         dd = hitWinObj->wo_DrawerData;
  381.         obj->wo_CurrentX += dd->dd_CurrentX;
  382.         obj->wo_CurrentY += dd->dd_CurrentY;
  383.         }
  384.         if (hitWin==wbWin) { /* To the backdrop */
  385.         /* A backdrop icon needs its very own lock,
  386.         in case its parent's drawer is later closed */
  387.         obj->wo_Lock = DupLock(obj->wo_Parent->
  388.             wo_DrawerData->dd_Lock);
  389.         if (debug) printf("Duplicate lock: <%s> %lx\n",
  390.             obj->wo_Name, obj->wo_Lock);
  391.         }
  392.  
  393.         else if (hitWinObj==obj->wo_Parent) {
  394.         /* Into the open drawer of my parent */
  395.         if (debug) printf("Oh Lawdy, I'se home--home at las'!\n");
  396.         /* I don't need my lock any more */
  397.         if (obj->wo_Lock) { /* Coming from the backdrop */
  398.             if (debug) printf("Unlocking <%s>: %lx\n",
  399.             obj->wo_Name, obj->wo_Lock);
  400.             UnLock(obj->wo_Lock);
  401.             obj->wo_Lock = NULL;
  402.         }
  403.         }
  404.  
  405.         else { /* Into some other open drawer */
  406.         lock = getlock(obj);
  407.         lock2 = hitWinObj->wo_DrawerData->dd_Lock;
  408.         if (vol(lock)==vol(lock2)) {
  409.             strcpy(buf1, obj->wo_Name); strcpy(buf2, obj->wo_Name);
  410.             if (debug) printf("Renaming %lx <%s> to %lx <%s>\n",
  411.             lock, buf1, lock2, buf2);
  412.             strcat(buf1, ".info"); strcat(buf2, ".info");
  413.             renBoth(lock, buf1, lock2, buf2);
  414.         }
  415.         else {
  416.             bs2cs(buf2, vol(lock2)->dl_Name);
  417. if (debug) printf("I should copy %lx <%s> to %lx <%s/%s> on <%s:>\n",
  418.             lock, obj->wo_Name, lock2,
  419.             hitWinObj->wo_Name, obj->wo_Name, buf2);
  420.         }
  421.         Remove(&obj->wo_Siblings);
  422.         AddHead(&dd->dd_Children, &obj->wo_Siblings);
  423.         obj->wo_Parent = hitWinObj;
  424.         }
  425.         obj->wo_IconWin = hitWin;
  426.     }
  427.     obj->wo_CurrentX += x;
  428.     obj->wo_CurrentY += y;
  429.     Remove(obj); AddTail(&wbObjs, obj);
  430.     /* So that refresh() draws it last (on top) */
  431.     }
  432.     doList(list, off, drawobj, HIGH);
  433.     doResize();
  434. }
  435.  
  436. mark(w) struct Window *w; { /* Mark window for later resizing */
  437.     if (w!=wbWin)
  438.         ((struct MyWBObject *)w->UserData)->wo_Flags |= RESIZE;
  439.     else wbFlags |= RESIZE;
  440. }
  441.  
  442. doResize() {
  443.     struct Node *node;
  444.     struct MyWBObject *obj;
  445.     struct Window *w;
  446.  
  447.     for (node=wbObjs.lh_Head; node->ln_Succ; node=node->ln_Succ) {
  448.     obj = (struct MyWBObject *)node;
  449.     if (obj->wo_Flags & RESIZE) {
  450.         w = obj->wo_DrawerData->dd_DrawerWin;
  451.         resize(w);
  452.         refresh(w);
  453.         obj->wo_Flags &= ~RESIZE;
  454.     }
  455.     }
  456.     if (wbFlags & RESIZE) {
  457.     /* It might be worth having a fake object whose drawer is
  458.     the backdrop, but all we really need is the Flags field */
  459.     refresh(wbWin);
  460.     wbFlags &= ~RESIZE;
  461.     }
  462. }
  463.  
  464. doGadDown () {
  465.     USHORT gid;
  466.     struct MyDrawerData *dd;
  467.     short shift;
  468.     long pos;
  469.  
  470.     gid = ((struct Gadget *)saveMsg.IAddress)->GadgetID;
  471.     dd = ((struct MyWBObject *)oldWin->UserData)->wo_DrawerData;
  472.     shift = saveMsg.Qualifier & SHIFT;
  473.     lastObj = NULL;
  474.  
  475.     switch (gid) {
  476.     case GID_VERTSCROLL: case GID_HORIZSCROLL: return;
  477.     case GID_LEFTSCROLL: pos = (ULONG)dd->dd_HorizProp.HorizPot;
  478.         dd->dd_CurrentX -= shift ? 1 : 20;
  479.         break;
  480.     case GID_RIGHTSCROLL: pos = (ULONG)dd->dd_HorizProp.HorizPot;
  481.         dd->dd_CurrentX += shift ? 1 : 20;
  482.         break;
  483.     case GID_UPSCROLL: pos = (ULONG)dd->dd_VertProp.VertPot;
  484.         dd->dd_CurrentY -= shift ? 1 : 10;
  485.         break;
  486.     case GID_DOWNSCROLL: pos = (ULONG)dd->dd_VertProp.VertPot;
  487.         dd->dd_CurrentY += shift ? 1 : 10;
  488.         break;
  489.     }
  490.     resize(oldWin);
  491.     SetRast(oldWin->RPort, 0L);
  492.     refresh(oldWin);
  493. }
  494.  
  495. doGadUp() {
  496.     USHORT gid;
  497.     struct MyDrawerData *dd;
  498.     long pos;
  499.  
  500.     gid = ((struct Gadget *)saveMsg.IAddress)->GadgetID;
  501.     dd = ((struct MyWBObject *)oldWin->UserData)->wo_DrawerData;
  502.  
  503.     switch (gid) {
  504.     case GID_HORIZSCROLL: /* I don't understand this either */
  505.     pos = (ULONG)dd->dd_HorizProp.HorizPot;
  506.     dd->dd_CurrentX = dd->dd_MinX + (pos *
  507.         (MAX(dd->dd_CurrentX, dd->dd_MaxX - (oldWin->Width-14L))
  508.          - MIN(dd->dd_CurrentX, dd->dd_MinX)) ) / MAXBODY; 
  509.     break;
  510.     case GID_VERTSCROLL:
  511.     pos = (ULONG)dd->dd_VertProp.VertPot;
  512.     dd->dd_CurrentY = dd->dd_MinY + (pos *
  513.         (MAX(dd->dd_CurrentY,dd->dd_MaxY-(oldWin->Height-YOFF-9L))
  514.          - MIN(dd->dd_CurrentY, dd->dd_MinY)) ) / MAXBODY;
  515.     break;
  516.     }
  517.     resize(oldWin);
  518.     SetRast(oldWin->RPort, 0L);
  519.     refresh(oldWin);
  520. }
  521.  
  522. /* Recalculate the size of a window's virtual coord system */
  523. resize(w) struct Window *w; {
  524.     struct Node *node;
  525.     struct MyWBObject *obj;
  526.     struct MyDrawerData *dd;
  527.     long effH, effW, total, left, right, pot, body;
  528.  
  529.     obj = (struct MyWBObject *)w->UserData;
  530.     dd = obj->wo_DrawerData;
  531.     dd->dd_MinX = dd->dd_MinY = 10000;
  532.     dd->dd_MaxX = dd->dd_MaxY = -10000;
  533.  
  534.     /* For each icon living in the window.. */
  535.     for (node=dd->dd_Children.lh_Head; node->ln_Succ;
  536.     node=node->ln_Succ) {
  537.         obj = OBJ(node,CHILD);
  538.         if (obj->wo_IconWin!=w) continue;
  539.  
  540.         /* Each icon contains two pieces..a title and an image */
  541.         /* Take the MIN of the left edges.. */
  542.         dd->dd_MinX = MIN(dd->dd_MinX,
  543.         obj->wo_CurrentX + obj->wo_NameXOffset);
  544.  
  545.         /* and the MAX of the right edges */
  546.         right = MAX(obj->wo_Gadget.Width,
  547.         obj->wo_NameXOffset + 8*strlen(obj->wo_Name));
  548.         dd->dd_MaxX = MAX(dd->dd_MaxX, obj->wo_CurrentX + right);
  549.  
  550.         /* Likewise top and bottom edges */
  551.         dd->dd_MinY = MIN(dd->dd_MinY, obj->wo_CurrentY);
  552.         dd->dd_MaxY = MAX(dd->dd_MaxY, obj->wo_CurrentY + 
  553.         obj->wo_Gadget.Height + 10L);
  554.     }
  555.  
  556.     /* Now recalculate the horizontal extent... */
  557.     /* total: Total size of virtual coord system */
  558.     /* left: Size undisplayed to left */
  559.     /* right: Size undisplayed to right */
  560.  
  561.     effW = w->Width-14L;
  562.     total = MAX(dd->dd_CurrentX + effW, dd->dd_MaxX)
  563.         - MIN(dd->dd_CurrentX, dd->dd_MinX);
  564.     left = MAX(dd->dd_CurrentX - dd->dd_MinX, 0L);
  565.     right = total - left - effW;
  566.     if ((left + right)==0L) pot = 0L;
  567.     else pot = (MAXBODY * left) / (left + right);
  568.     body = (MAXBODY * effW) / total;
  569.     ModifyProp(&dd->dd_HorizScroll, w, NULL, FREEHORIZ | AUTOKNOB,
  570.         pot, MAXBODY, body, MAXBODY);
  571.  
  572.     /* and the vertical extent */
  573.     effH = w->Height-YOFF-9L;
  574.     total = MAX(dd->dd_CurrentY + effH, dd->dd_MaxY)
  575.         - MIN(dd->dd_CurrentY, dd->dd_MinY);
  576.     left = MAX(dd->dd_CurrentY - dd->dd_MinY, 0L);
  577.     right = total - left - effH;
  578.  
  579.     if ((left + right)==0L) pot = 0L;
  580.     else pot = (MAXBODY * left) / (left + right);
  581.     body = (MAXBODY * effH) / total;
  582.     ModifyProp(&dd->dd_VertScroll, w, NULL, FREEVERT | AUTOKNOB,
  583.         MAXBODY, pot, MAXBODY, body);
  584. }
  585.  
  586. /* Must do this each time a window's size is changed */
  587. /* To prevent drawing over the borders */
  588. reclip(w) struct Window *w; {
  589.     struct Region *reg, *oldreg;
  590.  
  591.     reg = NewRegion();
  592.     rect.MaxX = w->Width - 19;
  593.     rect.MaxY = w->Height - 11;
  594.     OrRectRegion(reg, &rect);
  595.     oldreg = InstallClipRegion(w->WLayer, reg);
  596.     if (oldreg) DisposeRegion(oldreg);
  597. }
  598.  
  599. BPTR getlock(obj) struct MyWBObject *obj; {
  600.     BPTR lock;
  601.     char name[31];
  602.  
  603.     /* Either the obj's own Lock, or the Lock of the drawer it's in,
  604.     or manufacture a new one */
  605.     lock = obj->wo_Lock;
  606.     if (!lock) if (obj->wo_Parent)
  607.         lock = obj->wo_Parent->wo_DrawerData->dd_Lock;
  608.     if (!lock) { /* Presumably a disk */
  609.         if (debug) printf("%lx <%s> (a %s) needs a new lock\n",
  610.             obj, obj->wo_Name, type[obj->wo_Type]);
  611.         strcpy(name, obj->wo_Name);
  612.         strcat(name,":");
  613.         lock = obj->wo_Lock = Lock(name, ACCESS_READ);
  614.         /* Maybe user refused to reinsert disk */
  615.         if (!lock) printf("Can't lock <%s>\n", name);
  616.         if (debug) printf("getlock: new lock: %lx\n",lock);
  617.     }
  618.     return lock;
  619. }
  620.  
  621. struct DeviceList *vol(lock) BPTR lock; {
  622.     struct FileLock *fl;
  623.  
  624.     /* Return the Volume corresponding to a given Lock */
  625.     if (!lock) {printf("vol: Null lock\n"); return NULL;}
  626.     fl = (struct FileLock *)BADDR(lock);
  627.     return (struct DeviceList *)BADDR(fl->fl_Volume);
  628. }
  629.  
  630. /* Convert a BSTR to a C string */
  631. bs2cs(buf, bstr) char *buf; BPTR bstr; {
  632.     char *p;
  633.  
  634.     p = (char *)BADDR(bstr);
  635.     strncpy(buf, p+1, *p);
  636.     buf[*p] = 0;
  637. }
  638.  
  639. /* C string to BSTR - (buf must be Long Aligned) */
  640. cs2bs(buf, s) char *buf, *s; {
  641.     strcpy(buf+1, s);
  642.     *buf = strlen(s);
  643. }
  644.  
  645. renpkt(l1, n1, l2, n2) BPTR l1, l2; char *n1, *n2; {
  646.     long arg[4], res;
  647.     struct DeviceList *dl1, *dl2;
  648.     char *buf1, *buf2;
  649.     struct MsgPort *handid;
  650.  
  651.     if (debug) printf("Renpkt: <%s> to <%s>\n", n1, n2);
  652.     if (!l1 || !l2) {printf("renpkt error: null lock\n"); return;}
  653.     if ((dl1=vol(l1)) != (dl2=vol(l2)))
  654.         {printf("renpkt error: different volumes\n"); return;}
  655.     handid = ((struct FileLock *)BADDR(l1))->fl_Task;
  656.     /* Must be long aligned: */
  657.     buf1 = AllocMem(31L, MEMF_CPC); buf2 = AllocMem(31L, MEMF_CPC);
  658.     cs2bs(buf1, n1); cs2bs(buf2, n2);
  659.     arg[0] = l1; arg[2] = l2;
  660.     arg[1] = ((long)buf1)>>2; arg[3] = ((long)buf2)>>2;
  661.     if (!sendpkt(handid, ACTION_RENAME_OBJECT, arg, 4L))
  662.         printf("Rename failed\n");
  663.     FreeMem(buf1, 31L); FreeMem(buf2, 31L);
  664. }
  665.  
  666. renBoth(l1, n1, l2, n2) BPTR l1, l2; char *n1, *n2; {
  667.     /* Rename both the file and its .info file */
  668.     renpkt(l1, n1, l2, n2);
  669.     *rindex(n1,'.') = 0; *rindex(n2,'.') = 0;
  670.     renpkt(l1, n1, l2, n2);
  671. }
  672.  
  673. long tooSoon() {
  674.     long dt;
  675.  
  676.     dt = upSecs - downSecs;
  677.     if (dt>1) return FALSE;
  678.     dt = upMicros - downMicros + 1000000L*dt;
  679.     return (dt<200000L);
  680.     /* Two-tenths of a sec between selup and seldown
  681.     is too soon to count as a drag operation */
  682. }
  683.